package com.randi.framework.security.service;

import com.alibaba.fastjson2.JSON;
import com.randi.common.constant.Constants;
import com.randi.common.exception.user.UserNotExistsException;
import com.randi.common.exception.user.UserPasswordNotMatchException;
import com.randi.common.exception.user.UserPasswordRetryLimitExceedException;
import com.randi.common.utils.StringUtils;
import com.randi.common.core.domain.model.LoginUser;
import com.randi.common.enums.ResultCode;
import com.randi.common.core.domain.entity.SysUser;
import com.randi.common.exception.ServiceException;
import com.randi.system.domain.params.SysUserParam;
import com.randi.system.service.ISysUserService;
import com.randi.system.service.SysLogThreadService;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @author ziye
 */
@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Resource
    private ISysUserService iSysUserService;

    @Resource
    private PasswordService passwordService;

    @Resource
    private PermissionService permissionService;

    @Resource
    private SysLogThreadService sysLogThreadService;

    /**
     * 创建登录用户
     *
     * @param user sysUser
     * @return UserDetails
     */
    private UserDetails createLoginUser(SysUser user) {
        LoginUser loginUser = JSON.parseObject(JSON.toJSONString(user), LoginUser.class);
        loginUser.setUser(user);
        loginUser.setPermissions(permissionService.getPermissions(user));
        return loginUser;
    }

    /**
     * 根据用户名查询用户
     *
     * @param userName 用户名
     * @return 查询用户
     */
    private SysUser selectSysUserByName(String userName) {
        SysUserParam userParam = new SysUserParam();
        userParam.setUserName(userName);
        userParam.setUserNameFuzzy(false);
        return iSysUserService.selectSysUser(userParam);
    }


    @Override
    public UserDetails loadUserByUsername(String username) {
        SysUser sysUser = selectSysUserByName(username);

        if (sysUser == null) {
            // 账号不存在
            sysLogThreadService.handleLoginInfo(username, Constants.FAIL, ResultCode.LOGIN_USER_NOT_EXIST.message());
            throw new UserNotExistsException();
        } else if (passwordService.isLocking(username)) {
            // 密码输入错误过多锁定
            Integer retryCount = passwordService.getRetryCount(sysUser.getUserName());
            Integer lockingTime = passwordService.getLockingTime(username);
            String message = StringUtils.format(ResultCode.LOGIN_PASSWORD_ERROR_FAST_FORMAT.message(), retryCount, lockingTime);
            sysLogThreadService.handleLoginInfo(username, Constants.FAIL, message);
            throw new UserPasswordRetryLimitExceedException(retryCount, lockingTime);
        } else if (!passwordService.validatePassword(sysUser)) {
            // 密码输入错误
            Integer retryCount = passwordService.getRetryCount(sysUser.getUserName());
            String message = StringUtils.format(ResultCode.LOGIN_PASSWORD_ERROR_FORMAT.message(), retryCount);
            sysLogThreadService.handleLoginInfo(username, Constants.FAIL, message);
            throw new UserPasswordNotMatchException();
        } else if (sysUser.getStatus() == 1) {
            // 账号停用
            sysLogThreadService.handleLoginInfo(username, Constants.FAIL, ResultCode.LOGIN_USER_DISABLE.message());
            throw new ServiceException(ResultCode.LOGIN_USER_DISABLE);
        }

        // 登录成功日志
        sysLogThreadService.handleLoginInfo(username, Constants.SUCCESS, ResultCode.LOGIN_SUCCESS.message());
        return createLoginUser(sysUser);
    }

}
